package com.apes.auto.car.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.auto.car.model.*;
import com.apes.auto.car.repository.*;
import com.apes.auto.maintain.model.LatestCarModel;
import com.apes.auto.maintain.repository.LatestCarModelRepository;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.area.model.Country;
import com.apes.scm.masterdata.area.repository.CountryRepository;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.apes.auto.car.model.ImportCarConst.*;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;


/**
 * @ClassName ImportCarService
 * @Description TODO
 * @Author pengyb
 * @Date 2019/7/18 14:05
 * @Version 1.0
 **/
@Service("importCarService")
public class ImportCarService extends DomainService {

    @Autowired
    private ImportCarRepository importCarRepository;

    @Autowired
    private CarTypeConfigurationRepository carTypeConfigurationRepository;

    @Autowired
    private CarTypeConfigurationService configurationService;

    @Autowired
    private VehicleLabelRepository vehicleLabelRepository;

    @Autowired
    private CarSeriesRepository carSeriesRepository;

    @Autowired
    private VehicleTypeRepository vehicleTypeRepository;

    @Autowired
    private CarBrandRepository carBrandRepository;

    @Autowired
    private ManufacturersRepository manufacturersRepository;

    @Autowired
    private CountryRepository countryRepository;

    @Autowired
    private VehicleLabelService vehicleLabelService;

    @Autowired
    private WheelHubSpecificationsRepository wheelHubSpecificationsRepository;

    @Autowired
    private ImportCarExecuteRepository importCarExecuteRepository;

    private static Pattern NUMBER_PATTERN = Pattern.compile("-?[0-9]+(\\.[0-9]+)?");
    /**
     * 定义部分车型规则
     */
    public static Map<Integer, String> MATCHED_NK = new HashMap<Integer, String>();

    static {
        MATCHED_NK.put(1990, "N");
        MATCHED_NK.put(1991, "P");
        MATCHED_NK.put(1992, "Q");
        MATCHED_NK.put(1993, "R");
        MATCHED_NK.put(1994, "S");
        MATCHED_NK.put(1995, "T");
        MATCHED_NK.put(1996, "U");
        MATCHED_NK.put(1997, "V");
        MATCHED_NK.put(1998, "W");
        MATCHED_NK.put(1999, "X");
        MATCHED_NK.put(2000, "Y");
        MATCHED_NK.put(2001, "1");
        MATCHED_NK.put(2002, "2");
        MATCHED_NK.put(2003, "3");
        MATCHED_NK.put(2004, "4");
        MATCHED_NK.put(2005, "5");
        MATCHED_NK.put(2006, "6");
        MATCHED_NK.put(2007, "7");
        MATCHED_NK.put(2008, "8");
        MATCHED_NK.put(2009, "9");
        MATCHED_NK.put(2010, "A");
        MATCHED_NK.put(2011, "B");
        MATCHED_NK.put(2012, "C");
        MATCHED_NK.put(2013, "D");
        MATCHED_NK.put(2014, "E");
        MATCHED_NK.put(2015, "F");
        MATCHED_NK.put(2016, "G");
        MATCHED_NK.put(2017, "H");
        MATCHED_NK.put(2018, "J");
        MATCHED_NK.put(2019, "K");
        MATCHED_NK.put(2020, "L");
        MATCHED_NK.put(2021, "M");
        MATCHED_NK.put(2022, "N");
        MATCHED_NK.put(2023, "P");
        MATCHED_NK.put(2024, "R");
        MATCHED_NK.put(2025, "S");
        MATCHED_NK.put(2026, "T");
        MATCHED_NK.put(2027, "V");
        MATCHED_NK.put(2028, "W");
        MATCHED_NK.put(2029, "X");
        MATCHED_NK.put(2030, "Y");
    }


    /**
     * 保存
     *
     * @param request
     * @return
     */
    public ImportCar save(SimpleRequest request) {
        ImportCar car = request.getO(ImportCar.class);
        car.setLastUpdatedStamp(new Date());
        return importCarRepository.saveAndFlush(car);
    }


    public String delete(SimpleRequest request) {
        ImportCar o = request.getO(ImportCar.class);
        importCarRepository.delete(o.getId());
        return "删除成功";
    }

    /**
     * 执行
     *
     * @param request
     * @return
     */
    public ImportCar execute(SimpleRequest request) {
        ImportCar importCar = request.getO(ImportCar.class);
        List<Map> carTypeConfigurations = request.get("importCarExecutes");
        List<CarMatchingRule> carMatchingRules = new ArrayList<>();
        List<LatestCarModel> latestCarModels = new ArrayList<>();
        List<CarTypeConfiguration> configurations = new ArrayList<>();
        carTypeConfigurations.stream().forEach(carTypeConfiguration -> {
            CarTypeConfiguration configuration = MapUtil.getO(carTypeConfiguration, CarTypeConfiguration.class);
            configuration.setLRRQ_SJ(new Date());
            configuration.setTS01(DateUtil.format(configuration.getLRRQ_SJ(), "yyyyMMdd.hhmmss.SSS")); //时间戳
            configuration.setLRR(this.getPerson(request));  //录入人
            //保存
            // carTypeConfigurationRepository.saveAndFlush(configuration);
            configurations.add(configuration);
            //同步缩略表
            configurationService.syncCarThumbnail(configuration, carTypeConfiguration);
            if (!"0000000000001".equals(configuration.getPZCXID()) && !"JEKUN00000001".equals(configuration.getPZCXID()) && !"JQ00000000027".equals(configuration.getPZCXID()) && !"JQ00000000029".equals(configuration.getPZCXID()) && !"JQ00000000032".equals(configuration.getPZCXID())) {
                //同步电子目录
                if (configuration.getGGBZ().equals("新增")) {
                    configurationService.syncDZML(configuration);

                }
            }
            //同步最新车型表
            latestCarModels.add(configurationService.syncLatestCar(configuration));
            carMatchingRules.addAll(SpringManager.getBean(CarMatchingRuleService.class).syncMatchingRule(configuration));

        });
        carTypeConfigurationRepository.save(configurations);
        SpringManager.getBean(LatestCarModelRepository.class).save(latestCarModels);
        SpringManager.getBean(CarMatchingRuleRepository.class).save(carMatchingRules);
        importCarExecuteRepository.deleteAll(importCar.getImportCarExecutes());


        return importCar;
    }


    /**
     * 利用正则表达式来判断字符串是否为数字
     */
    public static boolean checkStrIsNum(String str) {
        String bigStr;
        try {
            /** 先将str转成BigDecimal，然后在转成String */
            bigStr = new BigDecimal(str).toString();
        } catch (Exception e) {
            /** 如果转换数字失败，说明该str并非全部为数字 */
            return false;
        }
        Matcher isNum = NUMBER_PATTERN.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }

    /**
     * 通用导入 车型配置
     *
     * @param request
     * @return
     */
    public JSONObject beImportCar(SimpleRequest request) {
        JSONObject importData = request.get("importData");//Excel信息
        JSONArray field = (JSONArray) request.get("data");
        //定义变量
        //List<ImportCarExecute> importCarExecutes = new ArrayList<>(); //用于批量保存车型配置中间表

        JSONObject exclObject = new JSONObject();                  //返回值

        JSONArray exclArr = new JSONArray();            //行内容
        JSONArray headerName = new JSONArray();         //头部
        JSONArray fieldName = new JSONArray();          //field

        for (int i = 0; i < field.size(); i++) {
            JSONObject webTab = (JSONObject) field.get(i);
            headerName.add(webTab.get("name"));
            fieldName.add(webTab.get("field"));
        }

        /**
         * 自定义缓存
         */
        Map map = customCache();

        //业务逻辑
        importData.forEach((k, v) -> {

            //获得value ===Excel内容
            JSONArray excl = (JSONArray) v;
            JSONArray header = (JSONArray) excl.get(0); //首行数据

            for (int i = 0; i < excl.size(); i++) {  //遍历每一行

                if (i == 0) { //跳过首行
                    exclArr.add(headerName);
                    continue;
                }

                JSONArray lineLong = (JSONArray) excl.get(i); //当前行

                //合并2个list为一个map,KEY为首行数据，Value为当前行数据
                Map<String, String> rst = IntStream.range(0, header.size()).collect(HashMap<String, String>::new,
                        (m, key) -> m.put(header.getString(key).replace(";", ""),
                                key >= lineLong.size() ? "" : (lineLong.getString(key) == null ? null : lineLong.getString(key).trim().replaceAll("[\\s]{2,}", " "))),
                        (m1, m2) -> {
                        });
                //主要数据检查
                checkMasterData(rst);
                //对车型ID的处理
                String[] FDJXHS = rst.get(FDJXH) == null ? "".split(";") : rst.get(FDJXH).split(";");

                int size = 0;
                if ("新增".equals(rst.get(BZ))) {
                    size = carTypeConfigurationRepository.findAllBylevelID(rst.get(LevelID));
                }

                if (FDJXHS.length > 1) {  //通常情况下车型ID为levelID加上尾数“0”，遇力洋多个发动机型号的情况则需拆分为多条车型ID，尾数依次叠加。

                    for (int j = 0; j < FDJXHS.length; j++) {

                        if ("新增".equals(rst.get(BZ))) {
                            JSONArray finishing = finishing(matchedCar(rst, FDJXHS[j], rst.get(LevelID) + (j + size), map), fieldName);
                            exclArr.add(finishing);

                        } else {
                            List<CarTypeConfiguration> carTypeConfigurations = new ArrayList<>();
                            carTypeConfigurations = Optional.of(carTypeConfigurationRepository.findAll(JpaDsl.toCriteriaByEq("levelID", rst.get(LevelID), "FDJXH", FDJXHS[j]))).orElse(new ArrayList<>());
                            if (carTypeConfigurations.size() == 0) {
                                throw new RuntimeException("标注为" + rst.get(BZ) + " 却无历史数据！请检查车型---------------车型ID为：" + rst.get(LevelID) + "~~~发动机型号：" + rst.get(FDJXH));
                            }
                            for (CarTypeConfiguration carTypeConfiguration : carTypeConfigurations) {
                                JSONArray finishing = finishing(matchedCar(rst, FDJXHS[j], carTypeConfiguration.getPZCXID(), map), fieldName);
                                exclArr.add(finishing);
                            }
                        }

                    }


                } else {

                    if ("新增".equals(rst.get(BZ))) {
                        JSONArray finishing = finishing(matchedCar(rst, rst.get(FDJXH), rst.get(LevelID) + size, map), fieldName);
                        exclArr.add(finishing);

                    } else {
                        List<CarTypeConfiguration> carTypeConfigurations = new ArrayList<>();
                        carTypeConfigurations = Optional.of(carTypeConfigurationRepository.findAll(JpaDsl.toCriteriaByEq("levelID", rst.get(LevelID), "FDJXH", rst.get(FDJXH)))).orElse(new ArrayList<>());

                        if (carTypeConfigurations.size() == 0) {
                            throw new RuntimeException("标注为" + rst.get(BZ) + " 却无历史数据！请检查车型---------------车型ID为：" + rst.get(LevelID) + "~~~发动机型号：" + rst.get(FDJXH));
                        }
                        for (CarTypeConfiguration carTypeConfiguration : carTypeConfigurations) {
                            JSONArray finishing = finishing(matchedCar(rst, rst.get(FDJXH), carTypeConfiguration.getPZCXID(), map), fieldName);
                            exclArr.add(finishing);
                        }

                    }


                }
            }
            exclObject.put(k, exclArr);
        });


        return exclObject;
    }

    /**
     * 主要数据检查
     *
     * @param rst
     */
    private void checkMasterData(Map<String, String> rst) {

        if (!"新增".equals(rst.get(BZ)) && !"修订".equals(rst.get(BZ)) && !"删除".equals(rst.get(BZ))) {
            throw new RuntimeException(rst.get(BZ) + ">>未知备注，请检查");
        }
        if (!rst.containsKey(LevelID)) {
            throw new RuntimeException("关键字段LevelID不存在，请检查");
        }
        if (!rst.containsKey(FDJXH)) {
            throw new RuntimeException("关键字段发动机型号不存在，请检查");
        }
        if (!rst.containsKey(BZ)) {
            throw new RuntimeException("关键字段更改备注不存在，请检查");
        }
    }

    /**
     * 自定义缓存、、
     *
     * @return
     */
    private Map customCache() {
        Map<String, HashMap> map = new HashMap();
        map.put("carBrandHashMap", new HashMap<String, CarBrand>());
        map.put("manufacturersHashMap", new HashMap<String, Manufacturers>());
        map.put("vehicleLabelHashMap", new HashMap<String, VehicleLabel>());
        map.put("carSeriesHashMap", new HashMap<String, CarSeries>());
        map.put("vehicleTypeHashMap", new HashMap<String, VehicleType>());
        map.put("GBHashMap", new HashMap<String, Country>());
        map.put("PZCXMCMap", new HashMap<String, Integer>());

        //自定义规则
        List<CustomCodeRules> customCodeRules = SpringManager.getBean(CustomCodeRulesRepository.class).findAll();
        map.put("customCodeRules", IntStream.range(0, customCodeRules.size()).collect(HashMap<String, String>::new,
                (m, index) ->
                        m.put(customCodeRules.get(index).getDescription(), customCodeRules.get(index).getCode()),
                (k1, k2) -> {
                }));
        //轮毂换算规则
        List<WheelHubSpecifications> hubSpecificationsList = wheelHubSpecificationsRepository.findAll();
        map.put("wheelHubSpecifications", IntStream.range(0, hubSpecificationsList.size()).collect(HashMap<String, String>::new,
                (m, index) ->
                        m.put(hubSpecificationsList.get(index).getTireWidth(), hubSpecificationsList.get(index).getWheeHubWidth()),
                (k1, k2) -> {
                }));
        //汽车类型
        List<AutoCategory> carTypes = SpringManager.getBean(AutoCategoryRepository.class).findAll();
        map.put("carTypes", IntStream.range(0, carTypes.size()).collect(HashMap<String, AutoCategory>::new,
                (m, index) ->
                        m.put(carTypes.get(index).getName(), carTypes.get(index)),
                (k1, k2) -> {
                }));

        //汽车等级
        List<AutoLevel> carLevels = SpringManager.getBean(AutoLevelRepository.class).findAll();
        map.put("carLevels", IntStream.range(0, carLevels.size()).collect(HashMap<String, AutoLevel>::new,
                (m, index) ->
                        m.put(carLevels.get(index).getName(), carLevels.get(index)),
                (k1, k2) -> {
                }));
        //排放等级
        List<AutoEmissionStandard> standards = SpringManager.getBean(AutoEmissionStandardRepository.class).findAll();
        map.put("emissionStandards", IntStream.range(0, standards.size()).collect(HashMap<String, AutoEmissionStandard>::new,
                (m, index) ->
                        m.put(standards.get(index).getName(), standards.get(index)),
                (k1, k2) -> {
                }));

        return map;
    }

    /**
     * 整理 排序 按前端顺序返回
     *
     * @param car
     * @param fieldName
     * @return
     */
    private JSONArray finishing(ImportCarExecute car, JSONArray fieldName) {
        JSONArray jsonCar = new JSONArray();
        Map<Object, Object> mapped = (Map<Object, Object>) MapUtil.mapped(car);
        for (int j = 0; j < fieldName.size(); j++) {
            if (mapped.containsKey(fieldName.getString(j))) {
                jsonCar.add(mapped.get(fieldName.getString(j)) == null || mapped.get(fieldName.getString(j)) == "" ? "" : mapped.get(fieldName.getString(j)));
            } else {
                jsonCar.add("");
            }
        }
        return jsonCar;
    }

    /**
     * 匹配数据
     *
     * @param rst
     * @param FDJXH
     * @param PZCXID
     * @return
     */
    public ImportCarExecute matchedCar(Map<String, String> rst, String FDJXH, String PZCXID, Map<String, HashMap> map) {
        ImportCarExecute car = new ImportCarExecute();
        car.setPZCXID(PZCXID); // 车型ID
        car.setFDJXH(FDJXH);    //发动机型号
        car.setFDJMS(rst.get(FDJMS)); //发动机描述
        car.setLevelID(rst.get(LevelID));

        car = matchedData(rst, car, map); //处理数据
        String XSMC = matchedXSMC(car, rst);

        /**
         *同一厂牌同一车型同一销售版本下，对应两个及以上发动机型号，则需在配置车型名称后加尾缀发动机型号，以空格间隔；
         */
        String PZCXMC = car.getVehicleLabel().getId() + "+" + car.getVehicleType().getId() + "+" + car.getXSBB();
        if (FDJXH != null) {
            if (map.get("PZCXMCMap").containsKey(PZCXMC)) {
                if ((int) map.get("PZCXMCMap").get(PZCXMC) == 0) {
                    FDJXH = null;
                }
            } else {
                List<CarTypeConfiguration> carConfigurations = Optional.ofNullable(carTypeConfigurationRepository.findAll(JpaDsl.toCriteriaByEq("vehicleLabel.id", car.getVehicleLabel().getId(), "vehicleType.id", car.getVehicleType().getId(), "XSBB", car.getXSBB()))).orElse(new ArrayList<>());
                if (carConfigurations.size() == 0) {
                    FDJXH = null;
                } else if (carConfigurations.stream().map(CarTypeConfiguration::getFDJXH).distinct().count() == 1) {
                    if (carConfigurations.get(0).getFDJXH() != null && carConfigurations.get(0).getFDJXH().equals(FDJXH)) {
                        FDJXH = null;
                    }
                }
                map.get("PZCXMCMap").put(PZCXMC, carConfigurations.size());
            }
            FDJXH = FDJXH == null ? "" : " " + FDJXH;

        }


        car.setPZCXMC((Optional.ofNullable(rst.get(SCNF)).orElse("") + "年" + " " + XSMC + FDJXH).trim());

        return car;
    }


    /**
     * 品牌
     *
     * @param brandName
     * @return
     */
    private CarBrand matchedCarBrand(String brandName, String YJFS, Map<String, CarBrand> carBrandHashMap) {
        //查询
        if (carBrandHashMap.containsKey(brandName)) {
            return carBrandHashMap.get(brandName);
        }
        CarBrand carBrand = carBrandRepository.findOne(JpaDsl.toCriteriaByEq("name", brandName)).orElse(null);

        if (carBrand == null) { //为空则新增
            CarBrand brand = new CarBrand();
            brand.setName(brandName);
            brand.setValid(true);
            brand.setCarCategory(YJFS);
            carBrand = carBrandRepository.saveAndFlush(brand);
        }
        carBrandHashMap.put(brandName, carBrand);
        return carBrand;

    }

    /**
     * 厂商
     *
     * @param name
     * @return
     */
    private Manufacturers matchedManufacturers(CarBrand carBrand, String name, Map<String, Manufacturers> manufacturersHashMap) {
        if (manufacturersHashMap.containsKey(name)) {
            return manufacturersHashMap.get(name);
        }
        name = checkCS(carBrand.getName(), name);
        //查询
        Manufacturers m;
        try {
            m = manufacturersRepository.findOne(JpaDsl.toCriteriaByEq("name", name)).orElse(null);
        } catch (Exception e) {
            throw new RuntimeException("厂商" + name + "查询出错");
        }


        if (m == null) {
            Manufacturers manufacturers = new Manufacturers();
            manufacturers.setName(name);
            m = manufacturersRepository.saveAndFlush(manufacturers);
        }
        manufacturersHashMap.put(name, m);
        return m;
    }

    /**
     * 厂牌
     * 1.“品牌”+“厂商”组合成厂牌，若一个品牌下只有一个厂商，则厂牌=厂商；若一个品牌下有多个厂商，则还需在表示进口的厂牌后边加上“(进口)”，如：奥迪汽车(进口)；
     * 2.系统中没有的新增厂牌名称需对其进行编码，具体规则如下：“厂牌编码”=国别编码+品牌首字母+厂商首字母。编码与名称为一对一关系，
     * 若有相同则做微调，国别编码保持不变，品牌及厂商编码优先取拼音中包含的字母，直至找到与现有编码不重合的组合。
     *
     * @param GB
     * @param carBrand
     * @param manufacturers
     * @return
     */
    private VehicleLabel matchedVehicleLabel(Country GB, CarBrand carBrand, Manufacturers manufacturers, String YJFS, Map<String, VehicleLabel> vehicleLabelHashMap) {
        String key = GB + "+" + carBrand.getId() + "+" + manufacturers.getId() + "+" + YJFS;
        if (vehicleLabelHashMap.containsKey(key)) {
            return vehicleLabelHashMap.get(key);
        }

        VehicleLabel vehicleLabel;
        //先查询该品牌有无厂牌
        List<VehicleLabel> vehicleLabels = Optional.of(vehicleLabelRepository.findAll(JpaDsl.toCriteriaByEq("carBrand.id", carBrand.getId()))).orElse(new ArrayList<>());
        //无则新增
        if (CollectionUtils.isEmpty(vehicleLabels)) {
            vehicleLabel = vehicleLabelService.matchedVehicleLabel(GB, carBrand, manufacturers, YJFS, true);

        } else { //该品牌有厂牌的情况下
            //根据 品牌和厂牌查找
            List<VehicleLabel> labels = Optional.of(vehicleLabels.stream().filter(v -> {
                return v.getCarBrand().getId().equals(carBrand.getId()) && v.getManufacturers().getId().equals(manufacturers.getId());
            }).collect(Collectors.toList())).orElse(new ArrayList<>());
            if (isNotEmpty(labels)) {
                //当厂商 品牌一致  直接返回
                return labels.get(0);
            } else { // 该品牌有厂牌 但厂商不一致  新增

                if (vehicleLabels.size() == 1) {
                    VehicleLabel label = vehicleLabels.get(0);
                    //修改第一个厂牌名称
                    if (label.getCarBrand().getCarCategory() != null && label.getCarBrand().getCarCategory().equals("进口")) {
                        label.setName(YJFS.equals("进口") ?
                                label.getCarBrand().getName() + "_" + label.getManufacturers().getName() + "(进口)"
                                : label.getManufacturers().getName() + "(进口)");
                    } else {
                        label.setName(label.getCarBrand().getName() + "_" + label.getManufacturers().getName());

                    }
                    vehicleLabel = vehicleLabelRepository.saveAndFlush(label);
                } else {
                    vehicleLabel = vehicleLabelService.matchedVehicleLabel(GB, carBrand, manufacturers, YJFS, false);

                }
            }
        }
        vehicleLabelHashMap.put(key, vehicleLabel);
        return vehicleLabel;
    }


    /**
     * 车系
     *
     * @param CX
     * @return
     */
    private CarSeries matchedCarSeries(String CX, CarBrand carBrand, Map<String, CarSeries> carSeriesHashMap) {
        //查询
        if (carSeriesHashMap.containsKey(CX + "+" + carBrand.getId())) {
            return carSeriesHashMap.get(CX + "+" + carBrand.getId());
        }
        CarSeries carSeries;
        try {
            carSeries = carSeriesRepository.findOne(JpaDsl.toCriteriaByEq("name", CX, "carBrand.id", carBrand.getId())).orElse(null);

        } catch (Exception e) {
            throw new RuntimeException("车系：" + CX + "查询错误");

        }

        if (carSeries == null) {
            CarSeries c = new CarSeries();
            c.setName(CX);
            c.setCarBrand(carBrand);
            carSeries = carSeriesRepository.saveAndFlush(c);
        }
        carSeriesHashMap.put(CX + "+" + carBrand.getId(), carSeries);
        return carSeries;
    }

    /**
     * 车型
     *
     * @param CX
     * @param carSeries
     * @return
     */
    private VehicleType matchedVehicleType(String CX, CarSeries carSeries, VehicleLabel vehicleLabel, Map<String, VehicleType> vehicleTypeHashMap) {
        if (vehicleTypeHashMap.containsKey(carSeries.getId() + "+" + CX + "+" + vehicleLabel.getId())) {
            return vehicleTypeHashMap.get(carSeries.getId() + "+" + CX + "+" + vehicleLabel.getId());
        }
        //查询
        VehicleType vehicleType;
        try {
            vehicleType = vehicleTypeRepository.findOne(JpaDsl.toCriteriaByEq("carSeries.id", carSeries.getId(), "name", CX.equals(carSeries.getName()) ? CX : carSeries.getName() + "_" + CX, "vehicleLabel.id", vehicleLabel.getId())).orElse(null);

        } catch (Exception e) {
            throw new RuntimeException("车型:" + CX + "查询出错");
        }

        if (vehicleType == null) {
            VehicleType v = new VehicleType();
            v.setSequence(v.checkSequence(vehicleLabel.getId()));
            v.setId(vehicleLabel.getId() + v.getSequence());
            v.setName(CX.equals(carSeries.getName()) ? CX : carSeries.getName() + "_" + CX);
            v.setCarSeries(carSeries);
            v.setVehicleLabel(vehicleLabel);
            vehicleType = vehicleTypeRepository.saveAndFlush(v);
        }
        vehicleTypeHashMap.put(carSeries.getId() + "+" + CX + "+" + vehicleLabel.getId(), vehicleType);
        return vehicleType;
    }

    /**
     * 档位数
     *
     * @param DWSL
     * @return
     */
    private int matchedDWSL(String DWSL) {
        String regEX = "[^0-9]";
        Matcher matcher = Pattern.compile(regEX).matcher(DWSL);
        return matcher.replaceAll("").trim().length() == 0 ? 0 : Integer.parseInt(matcher.replaceAll("").trim());
    }

    /**
     * 车型配件代码
     *
     * @param CXID
     * @param PL
     * @param NK
     * @param code
     * @return
     */
    private String matchedCXPJID(String CXID, String PL, int NK, String code) {
        if (PL == null || "电动".equals(PL)) {
            PL = "00";
        }
        PL = PL.replaceAll("\\.", "");

        String CXPJID = CXID + (PL.length() == 1 ? PL + "0" : PL) + MATCHED_NK.get(NK) + code;
        return CXPJID;
    }

    /**
     * 对配置车型名称的处理
     *
     * @param car
     * @param rst
     * @return
     */
    public String matchedXSMC(ImportCarExecute car, Map<String, String> rst) {
        // 对配置车型名称的处理
        /**
         * 1.“配置车型名称”=生产年份+销售名称+部分发动机型号，无单位排量需替换为有单位的；
         * 2.同一厂牌同一车型同一销售版本下，对应两个及以上发动机型号，则需在配置车型名称后加尾缀发动机型号，以空格间隔；
         * 3.前后不能留空，中间不能有连续两个空格。
         *理解：等于 => 遇力洋多个发动机型号的情况则需拆分为多条车型ID d
         *  无单位排量替换   通过正则找到第一个空格前的字符替换调 ^(?:\S*?)(\s)
         */
        //
        car.setXSBB(rst.get(XSBB));          //销售版本
        car.setCHXXSMC(rst.get(XSMC));       //销售名称
        car.setXSZT(rst.get(XSZT));          //销售状态
        car.setJQXS(rst.get(JQXS));          //进气形式
        car.setFDJPL(rst.get(PL) == null || rst.get(PL).equals("电动") ? null : (car.getJQXS().equals("自然吸气") ? (rst.get(PL).length() > 1 ? rst.get(PL) : rst.get(PL) + ".0") + "L" : (rst.get(PL).length() > 1 ? rst.get(PL) : rst.get(PL) + ".0") + "T"));//排量

        String regex = "^(?:\\S*?)(\\s)";
        //------配置车型用销售名称
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(car.getCHXXSMC());
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            //match.group() 是匹配的字符串
            String repeat = matcher.group();
            //appendReplacement用第二个参数去替换匹配成功的子串，并把结果存放在sb中，前面未匹配成功的也会放进去，后面的未匹配成功的不会放进去。例如：11123444546634 最后会替换成(1)23(4)54(6)
            matcher.appendReplacement(sb, repeat);
        }
        String PL = sb.toString();
        String XSMC = car.getCHXXSMC();
        if (checkStrIsNum(PL.trim())) {
            XSMC = car.getCHXXSMC().replace(PL, Optional.ofNullable(car.getFDJPL()).orElse("") + " ");
        }
        return XSMC;
    }

    /**
     * 轮毂
     *
     * @param LTGG
     * @param LGGG
     * @return
     */
    public String matchedLGGG(String LTGG, String LGGG, HashMap whsMap) {
        String s2 = null;
        String GG = null;

        if (null == LGGG) {
            s2 = LTGG.substring(LTGG.indexOf("R") + 1, LTGG.indexOf("R") + 3);
        } else {
            Matcher m = Pattern.compile("[\u4e00-\u9fa5]").matcher(LGGG);
            if (!m.find()) {
                return LGGG;
            }
            String regEX = "[^0-9]";
            Matcher matcher = Pattern.compile(regEX).matcher(LGGG);
            s2 = matcher.replaceAll("").trim();
        }

        try {
            String s1 = LTGG.substring(0, !LTGG.contains("/") ? (LTGG.indexOf(" ") == -1 ? LTGG.length() - 1 : LTGG.indexOf(" ")) : LTGG.indexOf("/"));
//          String s1 = LTGG.substring(0, LTGG.indexOf("/") == -1 ? (LTGG.indexOf(" ") == -1 ? LTGG.length() - 1 : LTGG.indexOf(" ")) : LTGG.indexOf("/"));
//            List<WheelHubSpecifications> hubSpecifications = Optional.ofNullable(wheelHubSpecifications.stream().filter(w -> w.getTireWidth().equals(s1)).collect(Collectors.toList())).orElse(new ArrayList<>());

            if (whsMap.containsKey(s1)) {
                GG = whsMap.get(s1) + "×" + s2;
            } else {
                GG = s1 + "×" + s2;
            }
        } catch (Exception e) {
            throw new RuntimeException("无此规格" + s2 + ":" + e);
        }


        return GG;


    }

    /**
     * 厂商修改检查
     *
     * @param PP
     * @param CJ
     * @return
     */
    public String checkCS(String PP, String CJ) {
        if (PP.equals("标致") && CJ.equals("神龙汽车")) {
            CJ = "神龙汽车(东风标致)";
        } else if (PP.equals("雪铁龙") && CJ.equals("神龙汽车")) {
            CJ = "神龙汽车(东风雪铁龙)";
        } else if (CJ.equals("上海通用") && (PP.equals("别克") || PP.equals("雪佛兰") || PP.equals("凯迪拉克"))) {
            CJ = "上汽通用";
        } else if (CJ.equals("上海大众") && (PP.equals("斯柯达") || PP.equals("大众"))) {
            CJ = "上汽大众";
        } else if (PP.equals("福特") && CJ.equals("长安福特马自达")) {
            CJ = "长安福特";
        } else if (PP.equals("马自达") && CJ.equals("长安福特马自达")) {
            CJ = "长安马自达";
        } else if (PP.equals("沃尔沃") && CJ.equals("沃尔沃亚太")) {
            CJ = "沃尔沃亚太吉利";
        }
        return CJ;
    }

    /**
     * 匹配国别字段
     *
     * @param name
     * @param GBHashMap
     * @return
     */
    public Country matchedCountry(String name, Map<String, Country> GBHashMap) {
        if (GBHashMap.containsKey(name)) {
            return GBHashMap.get(name);
        }
        Country country = countryRepository.findOne(JpaDsl.toCriteriaByEq("name", "捷克".equals(name) ? "捷克共和国" : ("俄罗斯".equals(name) ? "俄罗斯联邦" : name))).orElse(null);//国别
        GBHashMap.put(name, country);
        return country;
    }

    /**
     * 车型配置执行表匹配数据 ImportCarExecute
     *
     * @param rst
     * @return
     */
    public ImportCarExecute matchedData(Map<String, String> rst, ImportCarExecute car, Map<String, HashMap> map) {
        car.setGGBZ(rst.get(BZ));     //备注
        car.setYXBJ(!"删除".equals(car.getGGBZ())); //有效标记
        car.setLEVELFDJXH(rst.get(FDJXH));       //力洋发动机型号
        car.setYJFS(rst.get(GCHZJK)); //引进方式
        car.setCarBrand(matchedCarBrand(rst.get(PP), car.getYJFS(), map.get("carBrandHashMap"))); //汽车品牌
        car.setManufacturers(matchedManufacturers(car.getCarBrand(), rst.get(CJ), map.get("manufacturersHashMap")));     //汽车厂商

        //主数据 国家数据中 捷克 全称捷克共和国  俄罗斯有多个  此处取俄罗斯联邦
        car.setCountry(matchedCountry(rst.get(GB), map.get("GBHashMap"))); //国别
        car.setVehicleLabel(matchedVehicleLabel(car.getCountry(), car.getCarBrand(), car.getManufacturers(), car.getYJFS(), map.get("vehicleLabelHashMap")));//厂牌
        if (rst.get(NK) != null) {
            car.setNK(Integer.valueOf(rst.get(NK))); //年款
        }

        car.setCarSeries(matchedCarSeries(rst.get(CX), car.getCarBrand(), map.get("carSeriesHashMap")));  //车系
        car.setVehicleType(matchedVehicleType(rst.get(CHEXING), car.getCarSeries(), car.getVehicleLabel(), map.get("vehicleTypeHashMap"))); //车型
        car.setLevelCarType(rst.get(CHEXING)); //力洋车型

        //车辆类型
        if (null != rst.get(CLLX)) {
            Map carTypes = map.get("carTypes");
            if (!carTypes.containsKey(rst.get(CLLX).trim())) {
                throw new RuntimeException("车辆类型" + rst.get(CLLX).trim() + "不存在");
            }
            car.setCarType((AutoCategory) carTypes.get(rst.get(CLLX).trim()));
        }

        //车辆等级
        if (null != rst.get(CLJB)) {
            Map carLevels = map.get("carLevels");
            if (!carLevels.containsKey(rst.get(CLJB))) {
                throw new RuntimeException("车辆等级" + rst.get(CLJB) + "不存在");
            }
            car.setCarLevel((AutoLevel) carLevels.get(rst.get(CLJB).trim()));
        }

        //排放标准
        if (null != rst.get(PFBZ)) {
            Map standards = map.get("emissionStandards");
            if (!standards.containsKey(rst.get(PFBZ).trim())) {
                throw new RuntimeException("排放标准" + rst.get(PFBZ) + "不存在");
            }
            car.setAutoEmissionStandard((AutoEmissionStandard) standards.get(rst.get(PFBZ).trim()));
        }

        if (null != rst.get(DWS)) {
            car.setDWSL(matchedDWSL(rst.get(DWS)));//档位数
            car.setLEVELDWSL(rst.get(DWS));          //力洋档位数
        }

        if (null != rst.get(SSNF)) {
            if (checkStrIsNum(rst.get(SSNF))) {
                if (4 < rst.get(SSNF).length()) {
                    throw new RuntimeException("上市年份:" + rst.get(SSNF) + "超出正常范围或格式不对！请修改");
                }
                car.setSSNF(Integer.valueOf(rst.get(SSNF))); //上市年份
            } else {
                throw new RuntimeException("上市年份:" + rst.get(SSNF) + "不是数值类型！请修改");
            }
        }

        if (null != rst.get(SSYF)) {
            if (checkStrIsNum(rst.get(SSYF))) {
                if (2 < rst.get(SSYF).length()) {
                    throw new RuntimeException("上市月份:" + rst.get(SSYF) + "超出正常范围或格式不对！请修改");
                }
                car.setSSYF(Integer.valueOf(rst.get(SSYF)));  //上市月份
            } else {
                throw new RuntimeException("上市月份:" + rst.get(SSYF) + "不是数值类型！请修改");
            }
        }

        if (null != rst.get(SCNF)) {
            if (checkStrIsNum(rst.get(SCNF))) {
                if (4 < rst.get(SCNF).length()) {
                    throw new RuntimeException("生产年份:" + rst.get(SCNF) + "超出正常范围或格式不对！请修改");
                }
                car.setSCNF(Integer.valueOf(rst.get(SCNF)));  //生产年份
            } else {
                throw new RuntimeException("生产年份:" + rst.get(SCNF) + "不是数值类型！请修改");
            }
        }

        car.setTCNF(rst.get(TCNF));  //停产年份
        car.setSCZT(rst.get(SCZT)); //生产状态
        car.setQGRJ(rst.get(QGRJ)); //气缸容积
        car.setQGPLXS(rst.get(QGPLXS)); //气缸排列形式

        if (null != rst.get(QGS)) {
            car.setQGSL(Integer.valueOf(rst.get(QGS))); //气缸数

        }

        car.setRLLX(rst.get(RLLX)); //燃料类型
        car.setRLBH(rst.get(RYBH)); //燃油标号
        car.setZDML(rst.get(ZDML)); //最大马力

        car.setZDGL(rst.get(ZDGL)); //最大功率
//        car.setGearBoxModel();  //变速箱型号

        car.setBSXLB(rst.get(BSQLX)); //变速器类型
        car.setBSQMS(rst.get(BSQMS)); //变速器描述
        car.setQZDQLX(rst.get(QZDQ)); //前制动器类型

        car.setHZDQLX(rst.get(HZDQ)); //后制动器类型
        car.setZLLX(rst.get(ZLLX)); //助力类型
        car.setFDJWZ(rst.get(FDJWZ)); //发动机位置

        car.setQDFS(rst.get(QDFS)); //驱动方式
        car.setCSXS(rst.get(CSXS)); //车身形式
        car.setZHOUJ(rst.get(ZJ)); //轴距

        if (rst.get(CMS) != null) {
            car.setCMS(rst.get(CMS).equals("两门") ? "二门" : rst.get(CMS));  //车门数 “两门”改为“二门”
        }

        car.setZWSL(rst.get(ZWS)); //座位数
        car.setQLTGG(rst.get(QLTGG)); //前轮胎规格
        car.setHLTGG(rst.get(HLTGG)); //后轮胎规格

        if (rst.get(QLTGG) != null && !(rst.get(QLTGG).contains("J×")||rst.get(QLTGG).contains("Jx"))) {
            car.setQLGGG(matchedLGGG(rst.get(QLTGG), rst.get(QLGGG), map.get("wheelHubSpecifications"))); //前轮毂规格
        }

        if (rst.get(HLTGG) != null && !(rst.get(QLTGG).contains("J×")||rst.get(QLTGG).contains("Jx"))) {
            car.setHLGGG(matchedLGGG(rst.get(HLTGG), rst.get(HLGGG), map.get("wheelHubSpecifications"))); //后轮毂规格
        }


        car.setLGCL(rst.get(LGCL));  //轮毂材料
        car.setBTGG(rst.get(BTGG));  //备胎规格
        car.setDDTC(rst.get(DDTC));  //电动天窗

        car.setQJTC(rst.get(QJTC)); //全景天窗
        car.setXQDD(rst.get(XQDD)); //氙气大灯
        car.setQWD(rst.get(QWD)); //前雾灯

        car.setHYS(rst.get(HYS)); //后雨刷
        car.setKT(rst.get(KT)); //空调
        car.setZDKT(rst.get(ZDKT)); //自动空调

        car.setXSZDJ(rst.get(ZDJG) == null ? null : (rst.get(ZDJG).contains("$") ? "" : rst.get(ZDJG)));//货币形式为“$/美元”的部分清空

        //查找自定义代码规则 找到对应的代码
        if (!map.get("customCodeRules").containsKey(car.getBSQMS()))
            throw new RuntimeException("未找到该变速箱描述的自定义代码规则:" + car.getBSQMS());
        car.setCXPJID(matchedCXPJID(car.getVehicleType().getId(), rst.get(PL), car.getNK(), map.get("customCodeRules").get(car.getBSQMS()).toString())); //车型配件代码

        car.setCSCD(rst.get(C));//车身长度

        car.setCSKD(rst.get(K)); //车身宽度
        car.setCSGD(rst.get(G)); //车身高度
        car.setQLJ(rst.get(QLJ)); //前轮距

        car.setHLJ(rst.get(HLJ)); //后轮距
        car.setZXLDJX(rst.get(ZXLD)); //最小离地间隙
        car.setZBZL(rst.get(ZBZL)); //整备质量
//        car.setCSJG(); //车身结构
        car.setYXRJ(rst.get(YXRJ)); //油箱容积
        car.setXLXRJ(rst.get(XLXRJ)); //行李箱容积
        car.setFDJYSB(rst.get(YSB)); //压缩比

//        car.setFDJPQJG(); //配气机构
//        car.setFDJGJ(); //缸径
//        car.setFDJXC(); //行程

        car.setFDJZDGLZS(rst.get(ZDGLZS)); //最大功率转速
        car.setZDGLZS(rst.get(ZDGLZS)); //最大功率转速
        car.setFDJZDNJ(rst.get(ZDNJ)); //最大扭矩、
        car.setFDJZDNJZS(rst.get(ZDNJZS)); //最多扭矩转速

//        car.setFDJTYJS(); //发动机特有技术
        car.setFDJGYFS(rst.get(GYFS)); //供油方式
        car.setQXJLX(rst.get(QXGLX)); //前悬挂
        car.setHXJLX(rst.get(HXG)); //后悬挂

        car.setZFJSZAQQN(rst.get(JSSAQQN)); //驾驶座安全气囊
        car.setQHPCQN(rst.get(QPC)); //前排侧安全气囊
        car.setQHPTBQN(rst.get(QPTB));//前排侧头部

        car.setXBQN(rst.get(XBQN));
        car.setTYJCZZ(rst.get(TYJC));
        car.setLTYJXXS(rst.get(LTYJ));

        car.setAQDWXTS(rst.get(AQDWXTX));
        car.setETZYJK(rst.get(ISOFIX));
        car.setFDJDZFD(rst.get(FDJDZFD));

        car.setCNZKS(rst.get(ZKS));
        car.setYKYS(rst.get(YKYS));
        car.setMQGQMSL(rst.get(MGQM) == null ? 0 : Integer.valueOf(rst.get(MGQM)));

        car.setWYSQDXT(rst.get(WYSQD));
        car.setWYSJRXT(rst.get(WYSJRXT));
        car.setABSFBS(rst.get(ABS));

        car.setZDLFP(rst.get(ZDLFP));
        car.setSCFZ(rst.get(SCFZ));
        car.setQYLKZ(rst.get(QYLKZ));

        car.setCSWDKZ(rst.get(CSWDKZ));
        car.setDPHJ(rst.get(DPHJ));
        car.setKBXJ(rst.get(KBXG));

        car.setKQXJ(rst.get(KQXG));
        car.setKBZXB(rst.get(KBZX));
        car.setYDWGTJ(rst.get(YDWGTJ));

        car.setDDXHM(rst.get(DDXHM));
        car.setDDHBX(rst.get(DDHBX));
        car.setZPFXP(rst.get(ZPFX));

        car.setFXPTJ(rst.get(FXPSXTJ));
        car.setFXPDDTJ(rst.get(FXPDDTJ));
        car.setDGNFXP(rst.get(DGNFXP));

        car.setFXPHD(rst.get(FXPHD));
        car.setDSXH(rst.get(DSXH));
        car.setDCSPYX(rst.get(DCSP));

        car.setXCDNXSP(rst.get(XCDN));
        car.setHUDTTSZXS(rst.get(HUDTT));
        car.setZYCZ(rst.get(ZPZY));

        car.setYDFGZY(rst.get(YDZY));
        car.setZYGDTJ(rst.get(ZYGDTJ));
        car.setYBZCTJ(rst.get(YBZCTJ));

        car.setJBZCTJ(rst.get(JBZCTJ));
        car.setZFJSZDDTJ(rst.get(JSZZYTJ));
        car.setDEPKPJDTJ(rst.get(DEPZYTJ));

        car.setDEPZYYD(rst.get(DEPZYYD));
        car.setHPZYDDTJ(rst.get(HPZYTJ));
        car.setDDZYJY(rst.get(DDZYJY));

        car.setQHPZYJR(rst.get(QPZYJR));
        car.setQHPZYTF(rst.get(ZYTF));
        car.setQHPZYAM(rst.get(ZYAM));

        car.setDSPZY(rst.get(DSPZY));
        car.setHPZYFDFS(rst.get(HPZYZTFD));
        car.setQHZYFS(rst.get(QZZYFS));

        car.setHPBJ(rst.get(HPBJ));
        car.setGPSDHXT(rst.get(GPSDH));
        car.setDWHDFW(rst.get(DW));

        car.setZYTCSDP(rst.get(ZKTCSDP));
        car.setLYCZDH(rst.get(LYCZDH));
        car.setCZDS(rst.get(CZDS));

        car.setHPYJP(rst.get(HPYJP));
        car.setWJYYJK(rst.get(WJYYJK));
        car.setCDZC(rst.get(YPZC));

        car.setRJXCD(rst.get(RJXCD));
        car.setZDTD(rst.get(ZDTD));
        car.setZXTD(rst.get(ZXTD));

        car.setDDGDKT(rst.get(DDGDKT));
        car.setDDQXZZ(rst.get(DDQXZZ));
        car.setCNFWD(rst.get(CNFWD));

        car.setQHDDC(rst.get(QDDCC));
        car.setCCFJSGN(rst.get(CCFJ));
        car.setFZWXGRBL(rst.get(GRBL));

        car.setHSJDDTJ(rst.get(HSJDDTJ));
        car.setHSJJR(rst.get(HSJJR));
        car.setNWHSJZDFXM(rst.get(HSJZDFXM));

        car.setHSJDDZD(rst.get(HSJDDZD));
        car.setHSJJY(rst.get(HSJJY));
        car.setHFDZYL(rst.get(HFDZYL));

        car.setHPCZYL(rst.get(HPCZYL));
        car.setZYBHZJ(rst.get(ZYBHZJ));
        car.setGYYS(rst.get(GYYS));

        car.setHPDLKT(rst.get(HPDLKT));
        car.setHZCFK(rst.get(HZCFK));
        car.setWDFQKZ(rst.get(WDFQKZ));

        car.setCNKQTJ(rst.get(KQTJ));
        car.setCZBX(rst.get(CZBX));
        car.setZDBCRW(rst.get(ZDBCRW));

        car.setFDJQTJS(rst.get(FDJQTJS));
        car.setBXFZ(rst.get(BXFZ));
        car.setZDSC(rst.get(ZDSC));

        car.setZTZDZXXT(rst.get(ZDZX));
        car.setYSXT(rst.get(YSXT));
        car.setZKYJPFPXS(rst.get(ZKYJPFPXS));

        car.setZSYXH(rst.get(ZSYXH));
        car.setQJSST(rst.get(QJSXT));
        car.setYSQSL(rst.get(YSQSL));

        car.setPFBZMC(rst.get(PFBZ));
        car.setZGCS(rst.get(ZGCS));
        car.setNZYP(rst.get(NZYP));

        car.setLEDDD(rst.get(LEDDD));
        car.setZHGKYH(rst.get(ZHGKYH));
        car.setSQGKYH(rst.get(SQGKYH));

        car.setSJGKYH(rst.get(SJGKYH));
        car.setJSSJ(rst.get(JSSJ));
        car.setZXJXS(rst.get(ZXJX));

        car.setZXZWBJ(rst.get(ZXZW));
        car.setLQJ(rst.get(LQJ));
        car.setJJJ(rst.get(JJJ));

        car.setQDXS(rst.get(QDXS));
        car.setZDZZZL(rst.get(ZDZZ));
        car.setCDXS(rst.get(CDXS));

        car.setCPXS(rst.get(CPXS));
        car.setLATCH(rst.get(LATCH));
        car.setBCFZ(rst.get(BCFZ));

        car.setRJJHXT(rst.get(RJJHXT));
        car.setSDCD(rst.get(DDCD));
        car.setDDCD(rst.get(DUODIECD));

        car.setXYDDCD(rst.get(XNDDCD));
        car.setSDDVD(rst.get(DDDVD));
        car.setDDDVD(rst.get(DUODIEDVD));

        car.setDCLD(rst.get(DCLD));
        car.setCZXXFW(rst.get(CZXXFW));
        car.setNSYS(rst.get(NSYS));

        car.setCSYS(rst.get(CSYS));
        car.setFJSZAQQN(rst.get(FJSSAQQN));
        car.setHPCQN(rst.get(HPC));

        car.setHPTBQN(rst.get(HPTB));
        car.setFXPQHTJ(rst.get(FXPQHTJ));
        car.setFJSZDDTJ(rst.get(FJSZZYTJ));

        car.setHPZYJR(rst.get(HPZYJR));
        car.setHPZYBLFD(rst.get(HPZYBLFD));
        car.setHZYFS(rst.get(HZZYFS));

        car.setHDDC(rst.get(HDDCC));
        car.setZDZCSPFZ(rst.get(ZDZC));

        return car;
    }
}
